/*
  * FreeModbus Libary: LPC214X Port
  * Copyright (C) 2007 Tiago Prado Lone <tiago@maxwellbohr.com.br>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * File: $Id: portserial.c,v 1.1 2007/04/24 23:15:18 wolti Exp $
 */

#include "port.h"

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"
#include "mbport.h"
#include "bsp_usart.h"

/* ----------------------- Modbus includes ----------------------------------*/



/* ----------------------- Start implementation -----------------------------*/
void
EnterCriticalSection(  )
{
	__ASM volatile("cpsid i");
}

void
ExitCriticalSection(  )
{
	__ASM volatile("cpsie i");
}


/* ----------------------- Start implementation -----------------------------*/
void vMBPortSerialEnable( BOOL xRxEnable, BOOL xTxEnable )
{
	if(TRUE==xRxEnable)
	{
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
		RS485_RECEIVE_MODE;
	}
	else
	{
		USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);	
		RS485_SEND_MODE;
	}

	if(TRUE==xTxEnable)
	{
		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
		RS485_SEND_MODE;
	}
	else
	{
	   USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
		RS485_RECEIVE_MODE;
	}
}


BOOL
xMBPortSerialInit( UCHAR ucPORT, ULONG ulBaudRate, UCHAR ucDataBits, eMBParity eParity )
{
    GPIO_InitTypeDef	GPIO_InitStruct;
    USART_InitTypeDef	USART_InitStruct;
	  NVIC_InitTypeDef NVIC_InitStruct;     					//初始化NVIC结构体

	if(ucPORT==1)
	{
    //开启相关外设的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);    			//开启USART1的时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);   //开启GPIO的时钟

	
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_OUT;          //Tx管脚
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_Level_3;
    GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;   
    GPIO_Init(GPIOA,&GPIO_InitStruct);		
		GPIO_ResetBits(GPIOA,GPIO_Pin_8); //默认接收状态	
	
    /*
    PA9-TX-推挽复用
    PA10-RX-浮空输入/上拉输入
    */
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
    //配置USART的相应管脚的模式
    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;          //Tx管脚
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_Level_3;
    GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;   
    GPIO_Init(GPIOA,&GPIO_InitStruct);

    GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF;          //Rx管脚
    GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Speed=GPIO_Speed_Level_3;
    GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
    GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_NOPULL;   
    GPIO_Init(GPIOA,&GPIO_InitStruct);



     NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;    	//中断号
     NVIC_InitStruct.NVIC_IRQChannelPriority=1;              //抢占优先级1级
     NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;             //使能中断
     NVIC_Init(&NVIC_InitStruct );                         //执行初始化

    //配置串口的工作参数   即波特率=115200   数据长度=8bit    停止位=1bit   校验位=无  硬件流控制=无
    USART_InitStruct.USART_BaudRate=ulBaudRate;
    USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;     //配置模式(收发一起)
    USART_InitStruct.USART_Parity=USART_Parity_No ;
    USART_InitStruct.USART_StopBits=USART_StopBits_1;
    USART_InitStruct.USART_WordLength=USART_WordLength_8b;

    USART_Init(USART1,&USART_InitStruct);                 //DEBUG_USARTx一个结构体指针
    //选择具体的USART中断类型  (这个可靠吗???)
    USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);  //空闲中断 (有好几个中断,都可引起USART中断)
    //使能USART
    USART_Cmd(USART1,ENABLE);  
	}


	return TRUE;
}



BOOL
xMBPortSerialPutByte( CHAR ucByte )
{
	USART_SendData(USART1, ucByte);
  while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)/*ȴ*/
  {
  
  }		
	return TRUE;
}

BOOL
xMBPortSerialGetByte( CHAR * pucByte )
{
	*pucByte = USART_ReceiveData(USART1);
	return TRUE;
}

/* 
 * Create an interrupt handler for the transmit buffer empty interrupt
 * (or an equivalent) for your target processor. This function should then
 * call pxMBFrameCBTransmitterEmpty( ) which tells the protocol stack that
 * a new character can be sent. The protocol stack will then call 
 * xMBPortSerialPutByte( ) to send the character.
 */
void prvvUARTTxReadyISR(void)
{
    pxMBFrameCBTransmitterEmpty();
}

/* 
 * Create an interrupt handler for the receive interrupt for your target
 * processor. This function should then call pxMBFrameCBByteReceived( ). The
 * protocol stack will then call xMBPortSerialGetByte( ) to retrieve the
 * character.
 */
void prvvUARTRxISR(void)
{
    pxMBFrameCBByteReceived();
}

void USART1_IRQHandler(void)                	//串口1中断服务程序
{
		if(USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET)//没有这个会卡死在中断,数据益处中断
		{
				USART_ReceiveData(USART1);
				USART_ClearFlag(USART1, USART_FLAG_ORE);
		}
		
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{		
		prvvUARTRxISR();
		USART_ClearITPendingBit(USART1, USART_IT_RXNE);
	}

	if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
	{
		prvvUARTTxReadyISR();
	}	
} 
